package com.github.pavlospt;

import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.render.Arc;
import ohos.agp.render.Canvas;
import ohos.agp.render.Paint;
import ohos.agp.utils.Color;
import ohos.agp.utils.RectFloat;
import ohos.agp.utils.TextAlignment;
import ohos.app.Context;

/**
 * Circle view
 */
public class CircleView extends Component implements Component.DrawTask, Component.LayoutRefreshedListener {
    /**
     * * The constant CIRCLEVIEW_CV_TITLETEXT
     */
    public static final String CIRCLEVIEW_CV_TITLETEXT = "cv_titleText";
    /**
     * * The constant CIRCLEVIEW_CV_SUBTITLETEXT
     */
    public static final String CIRCLEVIEW_CV_SUBTITLETEXT = "cv_subtitleText";
    /**
     * * The constant CIRCLEVIEW_CV_TITLESIZE
     */
    public static final String CIRCLEVIEW_CV_TITLESIZE = "cv_titleSize";
    /**
     * * The constant CIRCLEVIEW_CV_SUBTITLESIZE
     */
    public static final String CIRCLEVIEW_CV_SUBTITLESIZE = "cv_subtitleSize";
    /**
     * * The constant CIRCLEVIEW_CV_TITLESUBTITLESPACE
     */
    public static final String CIRCLEVIEW_CV_TITLESUBTITLESPACE = "cv_titleSubtitleSpace";
    /**
     * * The constant CIRCLEVIEW_CV_STROKEWIDTHSIZE
     */
    public static final String CIRCLEVIEW_CV_STROKEWIDTHSIZE = "cv_strokeWidthSize";
    /**
     * * The constant CIRCLEVIEW_CV_FILLRADIUS
     */
    public static final String CIRCLEVIEW_CV_FILLRADIUS = "cv_fillRadius";
    /**
     * * The constant CIRCLEVIEW_CV_TITLECOLOR
     */
    public static final String CIRCLEVIEW_CV_TITLECOLOR = "cv_titleColor";
    /**
     * * The constant CIRCLEVIEW_CV_SUBTITLECOLOR
     */
    public static final String CIRCLEVIEW_CV_SUBTITLECOLOR = "cv_subtitleColor";
    /**
     * * The constant CIRCLEVIEW_CV_FILLCOLOR
     */
    public static final String CIRCLEVIEW_CV_FILLCOLOR = "cv_fillColor";
    /**
     * * The constant CIRCLEVIEW_CV_STROKECOLORVALUE
     */
    public static final String CIRCLEVIEW_CV_STROKECOLORVALUE = "cv_strokeColorValue";
    /**
     * * The constant CIRCLEVIEW_CV_BACKGROUNDCOLORVALUE
     */
    public static final String CIRCLEVIEW_CV_BACKGROUNDCOLORVALUE = "cv_backgroundColorValue";
    /**
     * * The constant DEFAULT_VIEW_SIZE
     */
    private static final int DEFAULT_VIEW_SIZE = 96;
    /**
     * * The constant DEFAULT_TITLE_COLOR
     */
    private static int DEFAULT_TITLE_COLOR = Color.CYAN.getValue();
    /**
     * * The constant DEFAULT_SUBTITLE_COLOR
     */
    private static int DEFAULT_SUBTITLE_COLOR = Color.WHITE.getValue();
    /**
     * * The constant DEFAULT_TITLE
     */
    private static String DEFAULT_TITLE = "Title";
    /**
     * * The constant DEFAULT_SUBTITLE
     */
    private static String DEFAULT_SUBTITLE = "Subtitle";
    /**
     * * The constant DEFAULT_SHOW_TITLE
     */
    private static boolean DEFAULT_SHOW_TITLE = true;
    /**
     * * The constant DEFAULT_SHOW_SUBTITLE
     */
    private static boolean DEFAULT_SHOW_SUBTITLE = true;
    /**
     * * The constant DEFAULT_TITLE_SIZE
     */
    private static float DEFAULT_TITLE_SIZE = 25f;
    /**
     * * The constant DEFAULT_SUBTITLE_SIZE
     */
    private static float DEFAULT_SUBTITLE_SIZE = 20f;
    /**
     * * The constant DEFAULT_TITLE_SUBTITLE_SPACE
     */
    private static float DEFAULT_TITLE_SUBTITLE_SPACE = 0f;
    /**
     * * The constant DEFAULT_STROKE_COLOR
     */
    private static int DEFAULT_STROKE_COLOR = Color.CYAN.getValue();
    /**
     * * The constant DEFAULT_BACKGROUND_COLOR
     */
    private static int DEFAULT_BACKGROUND_COLOR = Color.WHITE.getValue();
    /**
     * * The constant DEFAULT_FILL_COLOR
     */
    private static int DEFAULT_FILL_COLOR = Color.DKGRAY.getValue();
    /**
     * * The constant DEFAULT_STROKE_WIDTH
     */
    private static float DEFAULT_STROKE_WIDTH = 5f;
    /**
     * * The constant DEFAULT_FILL_RADIUS
     */
    private static float DEFAULT_FILL_RADIUS = 0.9f;
    /**
     * The constant M title color
     */
    private int mTitleColor = DEFAULT_TITLE_COLOR;
    /**
     * The constant M subtitle color
     */
    private int mSubtitleColor = DEFAULT_SUBTITLE_COLOR;
    /**
     * The constant M stroke color
     */
    private int mStrokeColor = DEFAULT_STROKE_COLOR;
    /**
     * The constant M background color
     */
    private int mBackgroundColor = DEFAULT_BACKGROUND_COLOR;
    /**
     * The constant M fill color
     */
    private int mFillColor = DEFAULT_FILL_COLOR;
    /**
     * The constant M title text
     */
    private String mTitleText = DEFAULT_TITLE;
    /**
     * The constant M subtitle text
     */
    private String mSubtitleText = DEFAULT_SUBTITLE;
    /**
     * The constant M title size
     */
    private float mTitleSize = DEFAULT_TITLE_SIZE;
    /**
     * The constant M subtitle size
     */
    private float mSubtitleSize = DEFAULT_SUBTITLE_SIZE;
    /**
     * The constant M stroke width
     */
    private float mStrokeWidth = DEFAULT_STROKE_WIDTH;
    /**
     * The constant M fill radius
     */
    private float mFillRadius = DEFAULT_FILL_RADIUS;
    /**
     * The constant M title subtitle space
     */
    private float mTitleSubtitleSpace = DEFAULT_TITLE_SUBTITLE_SPACE;
    /**
     * The constant M show title
     */
    private boolean mShowTitle = DEFAULT_SHOW_TITLE;
    /**
     * The constant M show subtitle
     */
    private boolean mShowSubtitle = DEFAULT_SHOW_SUBTITLE;
    /**
     * The constant M title text paint
     */
    private Paint mTitleTextPaint;
    /**
     * The constant M sub text paint
     */
    private Paint mSubTextPaint;
    /**
     * The constant M stroke paint
     */
    private Paint mStrokePaint;
    /**
     * The constant M background paint
     */
    private Paint mBackgroundPaint;
    /**
     * The constant M fill paint
     */
    private Paint mFillPaint;
    /**
     * The constant M inner rect f
     */
    private RectFloat mInnerRectF;
    /**
     * The constant M view size
     */
    private int mViewSize;
    /**
     * Upgrade SDK 5 to adapt to the onRefresh and onDraw sequences.
     */
    private boolean mIsOnRefreshed = false;


    /**
     * Circle view
     *
     * @param context context
     */
    public CircleView(Context context) {
        super(context);
        init(null);
    }

    /**
     * Circle view
     *
     * @param context context
     * @param attrs   attrs
     */
    public CircleView(Context context, AttrSet attrs) {
        this(context, attrs, null);
    }

    /**
     * Circle view
     *
     * @param context  context
     * @param attrs    attrs
     * @param defStyle def style
     */
    public CircleView(Context context, AttrSet attrs, String defStyle) {
        super(context, attrs, defStyle);
        init(attrs);
    }


    /**
     * Init *
     *
     * @param attrs attrs
     */
    private void init(AttrSet attrs) {
        mTitleText = AttrUtils.getStringFromAttr(attrs, CIRCLEVIEW_CV_TITLETEXT, "");
        mSubtitleText = AttrUtils.getStringFromAttr(attrs, CIRCLEVIEW_CV_SUBTITLETEXT, "");
        mTitleColor = AttrUtils.getColorFromAttr(attrs, CIRCLEVIEW_CV_TITLECOLOR, DEFAULT_TITLE_COLOR);
        mSubtitleColor = AttrUtils.getColorFromAttr(attrs, CIRCLEVIEW_CV_SUBTITLECOLOR, DEFAULT_SUBTITLE_COLOR);
        mBackgroundColor = AttrUtils.getColorFromAttr(attrs, CIRCLEVIEW_CV_BACKGROUNDCOLORVALUE, DEFAULT_BACKGROUND_COLOR);
        mStrokeColor = AttrUtils.getColorFromAttr(attrs, CIRCLEVIEW_CV_STROKECOLORVALUE, DEFAULT_STROKE_COLOR);
        mFillColor = AttrUtils.getColorFromAttr(attrs, CIRCLEVIEW_CV_FILLCOLOR, DEFAULT_FILL_COLOR);
        mTitleSize = AttrUtils.getDimensionFromAttr(attrs, CIRCLEVIEW_CV_TITLESIZE, (int) DEFAULT_TITLE_SIZE);
        mSubtitleSize = AttrUtils.getDimensionFromAttr(attrs, CIRCLEVIEW_CV_SUBTITLESIZE, (int) DEFAULT_SUBTITLE_SIZE);
        mStrokeWidth = AttrUtils.getFloatFromAttr(attrs, CIRCLEVIEW_CV_STROKEWIDTHSIZE, DEFAULT_STROKE_WIDTH);
        mFillRadius = AttrUtils.getFloatFromAttr(attrs, CIRCLEVIEW_CV_FILLRADIUS, DEFAULT_FILL_RADIUS);
        mTitleSubtitleSpace = AttrUtils.getFloatFromAttr(attrs, CIRCLEVIEW_CV_TITLESUBTITLESPACE, DEFAULT_TITLE_SUBTITLE_SPACE);

        // Title TextPaint
        mTitleTextPaint = new Paint();
        mTitleTextPaint.setAntiAlias(true);
        mTitleTextPaint.setTextAlign(TextAlignment.CENTER);
        mTitleTextPaint.setColor(new Color(mTitleColor));
        mTitleTextPaint.setTextSize((int) mTitleSize);

        // Subtitle TextPaint
        mSubTextPaint = new Paint();
        mSubTextPaint.setAntiAlias(true);
        mSubTextPaint.setTextAlign(TextAlignment.CENTER);
        mSubTextPaint.setColor(new Color(mSubtitleColor));
        mSubTextPaint.setTextSize((int) mSubtitleSize);

        // Stroke Paint
        mStrokePaint = new Paint();
        mStrokePaint.setAntiAlias(true);
        mStrokePaint.setStyle(Paint.Style.STROKE_STYLE);
        mStrokePaint.setColor(new Color(mStrokeColor));
        mStrokePaint.setStrokeWidth(mStrokeWidth);

        // Background Paint
        mBackgroundPaint = new Paint();
        mBackgroundPaint.setAntiAlias(true);
        mBackgroundPaint.setStyle(Paint.Style.FILL_STYLE);
        mBackgroundPaint.setColor(new Color(mBackgroundColor));

        // Fill Paint
        mFillPaint = new Paint();
        mFillPaint.setAntiAlias(true);
        mFillPaint.setStyle(Paint.Style.FILL_STYLE);
        mFillPaint.setColor(new Color(mFillColor));

        mInnerRectF = new RectFloat();
        setLayoutRefreshedListener(this);
        addDrawTask(this);
    }

    /**
     * On draw *
     *
     * @param component component
     * @param canvas    canvas
     */
    @Override
    public void onDraw(Component component, Canvas canvas) {
        if (!mIsOnRefreshed) {
            onRefreshed(component);
            mIsOnRefreshed = true;
        }
        mInnerRectF = new RectFloat(0, 0, mViewSize, mViewSize);
        mInnerRectF = offsetRectFolat(mInnerRectF, (getWidth() - mViewSize) / 2,
                (getHeight() - mViewSize) / 2);

        final int halfBorder = (int) (mStrokePaint.getStrokeWidth() / 2f + 0.5f);

        mInnerRectF = insertRectFolat(mInnerRectF, halfBorder, halfBorder);

        float centerX = mInnerRectF.getCenter().getPointX();
        float centerY = mInnerRectF.getCenter().getPointY();

        canvas.drawArc(mInnerRectF, new Arc(0, 360, true), mBackgroundPaint);

        float radius = (mViewSize / 2) * mFillRadius;

        canvas.drawCircle(centerX, centerY, radius + 0.5f - mStrokePaint.getStrokeWidth(), mFillPaint);

        int xPos = (int) centerX;
        int yPos = (int) (centerY - (mTitleTextPaint.descent() + mTitleTextPaint.ascent()) / 2);

        int subtitleXPos = (int) centerX;
        int subtitleYPos = (int) (centerY + (mTitleTextPaint.descent() - mTitleTextPaint.ascent()) / 2
                - mSubTextPaint.ascent());

        canvas.drawOval(mInnerRectF, mStrokePaint);

        if (mShowTitle) {
            canvas.drawText(mTitleTextPaint, mTitleText, xPos, yPos);
        }

        if (mShowSubtitle) {
            canvas.drawText(mSubTextPaint, mSubtitleText, subtitleXPos, subtitleYPos + mTitleSubtitleSpace);
        }
    }

    /**
     * Insert rect folat rect float
     *
     * @param mDrawableRect m drawable rect
     * @param mBorderWidth  m border width
     * @param mBorderHeight m border height
     * @return the rect float
     */
    private RectFloat insertRectFolat(RectFloat mDrawableRect, int mBorderWidth, int mBorderHeight) {
        float rectLeft = mDrawableRect.left + mBorderWidth;
        float rectRight = mDrawableRect.right - mBorderWidth;
        float rectTop = mDrawableRect.top + mBorderHeight;
        float rectBottom = mDrawableRect.bottom - mBorderHeight;
        return new RectFloat(rectLeft, rectTop, rectRight, rectBottom);
    }

    /**
     * Offset rect folat rect float
     *
     * @param mDrawableRect m drawable rect
     * @param mBorderWidth  m border width
     * @param mBorderHeight m border height
     * @return the rect float
     */
    private RectFloat offsetRectFolat(RectFloat mDrawableRect, int mBorderWidth, int mBorderHeight) {
        float rectLeft = mDrawableRect.left + mBorderWidth;
        float rectRight = mDrawableRect.right + mBorderWidth;
        float rectTop = mDrawableRect.top + mBorderHeight;
        float rectBottom = mDrawableRect.bottom + mBorderHeight;
        return new RectFloat(rectLeft, rectTop, rectRight, rectBottom);
    }

    /**
     * On refreshed *
     *
     * @param component component
     */
    @Override
    public void onRefreshed(Component component) {
        int width = getWidth();
        int height = getHeight();
        mViewSize = Math.min(width, height);
    }

    /**
     * Invalidate text paints
     */
    private void invalidateTextPaints() {
        mTitleTextPaint.setColor(new Color(mTitleColor));
        mSubTextPaint.setColor(new Color(mSubtitleColor));
        mTitleTextPaint.setTextSize((int) mTitleSize);
        mSubTextPaint.setTextSize((int) mSubtitleSize);
        invalidate();
    }

    /**
     * Invalidate paints
     */
    private void invalidatePaints() {
        mBackgroundPaint.setColor(new Color(mBackgroundColor));
        mStrokePaint.setColor(new Color(mStrokeColor));
        mFillPaint.setColor(new Color(mFillColor));
        invalidate();
    }


    /**
     * Sets whether the view's title string will be shown.
     *
     * @param flag The boolean value.
     */
    public void setShowTitle(boolean flag) {
        this.mShowTitle = flag;
        invalidate();
    }

    /**
     * Sets whether the view's subtitle string will be shown.
     *
     * @param flag The boolean value.
     */
    public void setShowSubtitle(boolean flag) {
        this.mShowSubtitle = flag;
        invalidate();
    }

    /**
     * Gets the title string attribute value.
     *
     * @return The title string attribute value.
     */
    public String getTitleText() {
        return mTitleText;
    }

    /**
     * Sets the view's title string attribute value.
     *
     * @param title The example string attribute value to use.
     */
    public void setTitleText(String title) {
        mTitleText = title;
        invalidate();
    }

    /**
     * Gets the subtitle string attribute value.
     *
     * @return The subtitle string attribute value.
     */
    public String getSubtitleText() {
        return mSubtitleText;
    }

    /**
     * Sets the view's subtitle string attribute value.
     *
     * @param subtitle The example string attribute value to use.
     */
    public void setSubtitleText(String subtitle) {
        mSubtitleText = subtitle;
        invalidate();
    }

    /**
     * Gets the stroke color attribute value.
     *
     * @return The stroke color attribute value.
     */
    public int getStrokeColor() {
        return mStrokeColor;
    }

    /**
     * Sets the view's stroke color attribute value.
     *
     * @param strokeColor The stroke color attribute value to use.
     */
    public void setStrokeColor(int strokeColor) {
        mStrokeColor = strokeColor;
        invalidatePaints();
    }

    /**
     * Gets the background color attribute value.
     *
     * @return The background color attribute value.
     */
    public int getBackgroundColor() {
        return mBackgroundColor;
    }

    /**
     * Sets the view's background color attribute value.
     *
     * @param backgroundColor The background color attribute value to use.
     */
    public void setBackgroundColor(int backgroundColor) {
        mBackgroundColor = backgroundColor;
        invalidatePaints();
    }

    /**
     * Gets the fill color attribute value.
     *
     * @return The fill color attribute value.
     */
    public int getFillColor() {
        return mStrokeColor;
    }

    /**
     * Sets the view's fill color attribute value.
     *
     * @param fillColor The fill color attribute value to use.
     */
    public void setFillColor(int fillColor) {
        mFillColor = fillColor;
        invalidatePaints();
    }

    /**
     * Gets the stroke width dimension attribute value.
     *
     * @return The stroke width dimension attribute value.
     */
    public float getStrokeWidth() {
        return mStrokeWidth;
    }

    /**
     * Sets the view's stroke width attribute value.
     *
     * @param strokeWidth The stroke width attribute value to use.
     */
    public void setStrokeWidth(float strokeWidth) {
        mStrokeWidth = strokeWidth;
        if (mStrokePaint != null) {
            mStrokePaint.setStrokeWidth(mStrokeWidth);
        }
        invalidate();
    }

    /**
     * Gets the fill radius dimension attribute value.
     *
     * @return The fill radius dimension attribute value.
     */
    public float getFillRadius() {
        return mFillRadius;
    }

    /**
     * Sets the view's fill radius attribute value.
     *
     * @param fillRadius The fill radius attribute value to use.
     */
    public void setFillRadius(float fillRadius) {
        mFillRadius = fillRadius;
        invalidate();
    }

    /**
     * Gets the title size dimension attribute value.
     *
     * @return The title size dimension attribute value.
     */
    public float getTitleSize() {
        return mTitleSize;
    }

    /**
     * Sets the view's title size dimension attribute value.
     *
     * @param titleSize The title size dimension attribute value to use.
     */
    public void setTitleSize(float titleSize) {
        mTitleSize = titleSize;
        invalidateTextPaints();
    }

    /**
     * Gets the subtitle size dimension attribute value.
     *
     * @return The subtitle size dimension attribute value.
     */
    public float getSubtitleSize() {
        return mSubtitleSize;
    }

    /**
     * Sets the view's subtitle size dimension attribute value.
     *
     * @param subtitleSize The subtitle size dimension attribute value to use.
     */
    public void setSubtitleSize(float subtitleSize) {
        mSubtitleSize = subtitleSize;
        invalidateTextPaints();
    }

    /**
     * Gets the title text color attribute value.
     *
     * @return The text color attribute value.
     */
    public int getTitleColor() {
        return mTitleColor;
    }

    /**
     * Sets the view's title text color attribute value.
     *
     * @param titleColor The title text color attribute value to use.
     */
    public void setTitleColor(int titleColor) {
        mTitleColor = titleColor;
        invalidateTextPaints();
    }

    /**
     * Gets the subtitle text color attribute value.
     *
     * @return The text color attribute value.
     */
    public int getSubtitleColor() {
        return mSubtitleColor;
    }

    /**
     * Sets the view's subtitle text color attribute value.
     *
     * @param subtitleColor The subtitle text color attribute value to use.
     */
    public void setSubtitleColor(int subtitleColor) {
        mSubtitleColor = subtitleColor;
        invalidateTextPaints();
    }

    /**
     * Gets the title subtitle space attribute value.
     *
     * @return The title subtitle space attribute value.
     */
    public float getTitleSubtitleSpace() {
        return mTitleSubtitleSpace;
    }

    /**
     * Sets the view's title subtitle space attribute value.
     *
     * @param titleSubtitleSpace The space between title and subtitle attribute value to use.
     */
    public void setTitleSubtitleSpace(float titleSubtitleSpace) {
        this.mTitleSubtitleSpace = titleSubtitleSpace;
        invalidateTextPaints();
    }
}
